/* VlcSoundControl widget */

#include "vlcsoundcontrol.h"

#include "pixmaps/audio_volume_muted.h"
#include "pixmaps/audio_volume_low.h"
#include "pixmaps/audio_volume_medium.h"
#include "pixmaps/audio_volume_high.h"

#define DEFAULT_SOUND_VALUE 125.0

enum {
  VLC_SOUND_CONTROL_VALUE_CHANGED,
  VLC_SND_NUMBER_OF_SIGNALS
};

static void     vlc_sound_control_class_init (VlcSoundControlClass *klass);
static void     vlc_sound_control_init       (VlcSoundControl *sound);
static void     vlc_sound_control_destroy    (GtkObject *object);

static void     vlc_sound_control_set_button_state (VlcSoundControl *sound_control);

static void     cb_toggled_button (GtkToggleButton *togglebutton, gpointer user_data);
static gboolean cb_change_value_hscale (GtkRange *range, GtkScrollType scroll, gdouble value, gpointer user_data);

G_DEFINE_TYPE (VlcSoundControl, vlc_sound_control, GTK_TYPE_HBOX);

static guint vlcsoundcontrol_signals [VLC_SND_NUMBER_OF_SIGNALS] = { 0 };

static void
vlc_sound_control_class_init (VlcSoundControlClass *klass)
{

  GtkObjectClass *object_class;

  object_class = GTK_OBJECT_CLASS (klass);

  object_class->destroy = vlc_sound_control_destroy;

  /* Sound Value Changed Signal */
  vlcsoundcontrol_signals[VLC_SOUND_CONTROL_VALUE_CHANGED] = g_signal_new ("sound-value-changed",
    G_TYPE_FROM_CLASS (klass),
    G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
    G_STRUCT_OFFSET (VlcSoundControlClass, sound_value_changed),
    NULL,
    NULL,
    g_cclosure_marshal_VOID__DOUBLE,
    G_TYPE_NONE, 1,
    G_TYPE_DOUBLE);

}

static void
vlc_sound_control_init (VlcSoundControl *sound_control)
{

  sound_control->value = DEFAULT_SOUND_VALUE;
  sound_control->muted_value = DEFAULT_SOUND_VALUE;
  
  sound_control->audio_muted = gdk_pixbuf_new_from_inline (-1, audio_volume_muted, FALSE, NULL);
  sound_control->audio_low = gdk_pixbuf_new_from_inline (-1, audio_volume_low, FALSE, NULL);
  sound_control->audio_medium = gdk_pixbuf_new_from_inline (-1, audio_volume_medium, FALSE, NULL);
  sound_control->audio_high = gdk_pixbuf_new_from_inline (-1, audio_volume_high, FALSE, NULL);

  gtk_box_set_spacing (GTK_BOX (sound_control), 2);
  gtk_box_set_homogeneous (GTK_BOX (sound_control), FALSE);

  sound_control->button = gtk_toggle_button_new ();
  gtk_button_set_relief (GTK_BUTTON (sound_control->button), GTK_RELIEF_NONE);
  gtk_button_set_image (GTK_BUTTON (sound_control->button), gtk_image_new_from_pixbuf (sound_control->audio_medium ));
  gtk_button_set_focus_on_click (GTK_BUTTON (sound_control->button), FALSE);
  g_signal_connect (G_OBJECT (sound_control->button), "toggled", G_CALLBACK (cb_toggled_button), sound_control);
  gtk_box_pack_start (GTK_BOX (sound_control), sound_control->button, FALSE, FALSE, 0);

  sound_control->hscale = gtk_hscale_new_with_range (0.0, 200.0, 10.0);
  gtk_scale_set_draw_value (GTK_SCALE (sound_control->hscale), FALSE);
  gtk_range_set_value (GTK_RANGE (sound_control->hscale), DEFAULT_SOUND_VALUE);
  gtk_widget_set_size_request (GTK_WIDGET (sound_control->hscale), 96, -1);
  g_signal_connect (G_OBJECT (sound_control->hscale), "change-value", G_CALLBACK (cb_change_value_hscale), sound_control);
  gtk_box_pack_start (GTK_BOX (sound_control), sound_control->hscale, FALSE, FALSE, 0);

}

GtkWidget*
vlc_sound_control_new ()
{

  return g_object_new (VLC_TYPE_SOUND_CONTROL, NULL);

}

static void
cb_toggled_button (GtkToggleButton *togglebutton, gpointer user_data)
{

  VlcSoundControl *sound_control;
  gdouble value;

  sound_control = VLC_SOUND_CONTROL (user_data);

  if (gtk_toggle_button_get_active (togglebutton))
   {
    sound_control->muted_value = sound_control->value;
    value = 0;
   }
  else /* restore sound value before mute action */
   {
    value = sound_control->muted_value;
   }
   
  gtk_range_set_value (GTK_RANGE (sound_control->hscale), value);
  vlc_sound_control_set_button_state (sound_control);
  sound_control->value = value;

  g_signal_emit (G_OBJECT (sound_control),
    vlcsoundcontrol_signals[VLC_SOUND_CONTROL_VALUE_CHANGED],
    0,
    value);

}

static gboolean
cb_change_value_hscale (GtkRange *range, GtkScrollType scroll, gdouble value, gpointer user_data)
{

  if (value < 0)
   {
    value = 0.0;
   }
  else if (value > 200)
   {
    value = 200.0;
   }
  
  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (VLC_SOUND_CONTROL (user_data)->button)) && value > 0)
   {
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (VLC_SOUND_CONTROL (user_data)->button), FALSE);
   }
  
  gtk_range_set_value (range, value);
  vlc_sound_control_set_button_state (VLC_SOUND_CONTROL (user_data));

  g_signal_emit (G_OBJECT (user_data),
    vlcsoundcontrol_signals[VLC_SOUND_CONTROL_VALUE_CHANGED],
    0,
    value);

  (void)scroll;

  return TRUE;
  
}

static void
vlc_sound_control_set_button_state (VlcSoundControl *sound_control)
{

  GtkWidget *image;
  GdkPixbuf *pixbuf;
  gboolean change_state = FALSE;
  gdouble value;

  value = gtk_range_get_value (GTK_RANGE (sound_control->hscale));

  if (value == 0.0)
   {
     pixbuf = sound_control->audio_muted;
     change_state = (sound_control->value > 0.0);
   }
  else if (value > 0.0 && value <= 66.0)
   {
     pixbuf = sound_control->audio_low;
     change_state = (sound_control->value > 33.0 || sound_control->value == 0.0);
   }
  else if (value > 66.0 && value <= 122.0)
   {
     pixbuf = sound_control->audio_medium;
     change_state = (sound_control->value < 66.0 || sound_control->value > 122.0);
   }
  else
   {
     pixbuf = sound_control->audio_high;
     change_state = (sound_control->value < 122.0);
   }

  if (change_state)
   {
    image = gtk_button_get_image (GTK_BUTTON (sound_control->button));
    gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
   }

  sound_control->value = value;

}

static void
vlc_sound_control_destroy (GtkObject *object)
{

  VlcSoundControlClass *klass;
  VlcSoundControl *sound_control;

  g_return_if_fail (object != NULL);
  g_return_if_fail (VLC_IS_SOUND_CONTROL (object));

  sound_control = VLC_SOUND_CONTROL (object);

  if (sound_control->audio_muted != NULL)
   {
    g_object_unref (sound_control->audio_muted);
    sound_control->audio_muted = NULL;
   }

  if (sound_control->audio_low != NULL)
   {
    g_object_unref (sound_control->audio_low);
    sound_control->audio_low = NULL;
   }

  if (sound_control->audio_medium != NULL)
   {
    g_object_unref (sound_control->audio_medium);
    sound_control->audio_medium = NULL;
   }

  if (sound_control->audio_high != NULL)
   {
    g_object_unref (sound_control->audio_high);
    sound_control->audio_high = NULL;
   }

  klass = gtk_type_class (gtk_hbox_get_type ());

  if (GTK_OBJECT_CLASS (klass)->destroy)
   {
    (* GTK_OBJECT_CLASS (klass)->destroy) (object);
   }

}

